package org.office.excel.convertor;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.office.api.constants.ExcelConstants;
import org.office.api.constants.FileConstans;
import org.office.api.convertor.AbstractConvertor;
import org.office.api.model.ModelAttribute;
import org.office.api.model.ModelClass;
import org.office.api.utils.ExcelUtil;

/** 
 * <pre>
 * Excel转换器，每一个sheet都需要配置，
 * 配置文件中的一个class节点对应一个sheet
 * </pre>
 *
 * <pre> 
 * 构建组：office-excel
 * 作者：eddy
 * 邮箱：1546077710@qq.com
 * 日期：2016年11月2日-下午4:25:16
 * 版权：
 * </pre>
 */
public class ExcelDiffConvertor extends AbstractConvertor {
	private Logger logger = Logger.getLogger(getClass());

	@Override
	public String type() {
		return FileConstans.EXCEL;
	}

	@Override
	public List<ModelClass> readData(String fileName, InputStream stream, List<ModelClass> modelClassList) throws IOException {
		if (null == fileName || "".equals(fileName)) {
			throw new IOException("文件名为空！");
		}
		
		if (null == stream) {
			throw new IOException("文件流为空！");
		}
		
		if (null == modelClassList || 0 == modelClassList.size()) {
			throw new IOException("模型对象列表为空！");
		}
		
		String postfix = ExcelUtil.getPostfix(fileName);
		if (ExcelConstants.EMPTY.equals(postfix)) {
			throw new IOException(fileName + ExcelConstants.NOT_EXCEL_FILE);
		}
		
		if (ExcelConstants.EXCEL_2003_POSTFIX.equalsIgnoreCase(postfix)) {
			return readXls(stream, modelClassList);
		} else if (ExcelConstants.EXCEL_2007_POSTFIX.equalsIgnoreCase(postfix)) {
			return readXlsx(stream, modelClassList);
		}else{
			throw new IOException(fileName + ExcelConstants.UNKNOW_FILE);
		}
	}
	
	@Override
	public List<ModelClass> readData(String fileName, InputStream stream, ModelClass modelClass)throws IOException{
		if (null == fileName || "".equals(fileName)) {
			throw new IOException("文件名为空！");
		}
		
		if (null == stream) {
			throw new IOException("文件流为空！");
		}
		
		if (null == modelClass) {
			throw new IOException("模型对象为空！");
		}
		
		if (null == modelClass.getAttributes() || modelClass.getAttributes().size() < 1) {
			throw new IOException("模型对象属性列表为空！");
		}
		
		String postfix = ExcelUtil.getPostfix(fileName);
		if (ExcelConstants.EMPTY.equals(postfix)) {
			throw new IOException(fileName + ExcelConstants.NOT_EXCEL_FILE);
		}
		
		if (ExcelConstants.EXCEL_2003_POSTFIX.equalsIgnoreCase(postfix)) {
			HSSFWorkbook hssfWorkbook = new HSSFWorkbook(stream);
			
			// Read the Sheet
			int sheet = modelClass.getSn();
			logger.debug("read sheet number:" + sheet);
			HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(sheet);
			if(null == hssfSheet) {
				//hssfWorkbook.close(); //3.8-beta4没有这个方法
				return Collections.emptyList();
			}
			logger.debug("read sheet name:" + hssfSheet.getSheetName());
			List<ModelClass> rs = readXls(hssfSheet, modelClass);
			//hssfWorkbook.close(); //3.8-beta4没有这个方法
			return rs;
		} else if (ExcelConstants.EXCEL_2007_POSTFIX.equalsIgnoreCase(postfix)) {
			XSSFWorkbook xssfWorkbook = new XSSFWorkbook(stream);
			
			// Read the Sheet
			int sheet = modelClass.getSn();
			logger.debug("read sheet number:" + sheet);
			XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(sheet);
			if(null == xssfSheet) {
				//xssfWorkbook.close(); //3.8-beta4没有这个方法
				return Collections.emptyList();
			}
			logger.debug("read sheet name:" + xssfSheet.getSheetName());
			List<ModelClass> rs = readXlsx(xssfSheet, modelClass);
			//xssfWorkbook.close(); //3.8-beta4没有这个方法
			return rs;
		}else{
			throw new IOException(fileName + ExcelConstants.UNKNOW_FILE);
		}
	}
	
	@Override
	public List<ModelClass> readData(String fileName, String filePath, ModelClass modelClass)throws IOException{
		if(null == filePath || "".equals(filePath)) throw new IOException("文件路径为空！");
		
		InputStream stream = new FileInputStream(filePath);
		return readData(fileName, stream, modelClass);
	}
	
	/**
	 * 读取Excel 2003
	 *
	 * @param stream
	 * @param modelClassList
	 * @return
	 * @throws IOException 
	 */
	public static List<ModelClass> readXls(InputStream stream, List<ModelClass> modelClassList) throws IOException {
		HSSFWorkbook hssfWorkbook = new HSSFWorkbook(stream);
		List<ModelClass> results = new ArrayList<ModelClass>();
		
		for(ModelClass model : modelClassList){
			List<ModelAttribute> attributes = model.getAttributes();
			if(null == attributes || 0 == attributes.size()) {
				//hssfWorkbook.close(); //3.8-beta4没有这个方法
				throw new IOException("模型对象属性列表为空！");
			}
			
			// Read the Sheet
			int sheet = model.getSn();
			HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(sheet);
			if(null == hssfSheet) {
				//hssfWorkbook.close(); //3.8-beta4没有这个方法
				throw new IOException("工作簿" + (sheet + 1) + "不存在！");
			}
			
			List<ModelClass> tmpModelList = readXls(hssfSheet, model);
			if(null == tmpModelList || tmpModelList.size() < 1) continue;
			
			results.addAll(tmpModelList);
		}
		
		//hssfWorkbook.close(); //3.8-beta4没有这个方法
		
		return results;
	}
	
	/**
	 * 读取Excel 2007
	 *
	 * @param stream
	 * @param modelClassList
	 * @return
	 * @throws IOException 
	 */
	public static List<ModelClass> readXlsx(InputStream stream, List<ModelClass> modelClassList) throws IOException {
		XSSFWorkbook xssfWorkbook = new XSSFWorkbook(stream);
		List<ModelClass> results = new ArrayList<ModelClass>();
		
		for(ModelClass model : modelClassList){
			List<ModelAttribute> attributes = model.getAttributes();
			if(null == attributes || 0 == attributes.size()) {
				//xssfWorkbook.close(); //3.8-beta4没有这个方法
				throw new IOException("模型对象属性列表为空！");
			}
			
			// Read the Sheet
			int sheet = model.getSn();
			XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(sheet);
			if(null == xssfSheet) continue;
			
			List<ModelClass> tmpModelList = readXlsx(xssfSheet, model);
			if(null == tmpModelList || tmpModelList.size() < 1) continue;
			
			results.addAll(tmpModelList);
		}
		
		//xssfWorkbook.close(); //3.8-beta4没有这个方法
		
		return results;
	}

}
